package com.tianquan.miracle.context;

import com.tianquan.miracle.beans.DefaultBeanFactory;
import com.tianquan.miracle.listener.core.EventListener;
import com.tianquan.miracle.listener.core.EventObject;
import com.tianquan.miracle.listener.core.EventSourceManager;
import com.tianquan.miracle.listener.refreshed.ContextRefreshedEvent;
import com.tianquan.miracle.util.MiracleUtils;
import com.tianquan.miracle.util.ServiceClassLoader;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @Author: tianquan
 * @date: 2024-09-28  22:31
 * @Description: 通用上下文容器
 */
public abstract class GeneralApplicationContext extends AbstractApplicationContext {

    private DefaultBeanFactory beanFactory;

    private EventSourceManager eventSourceManager;

    private long startTime;

    @Override
    public void refresh() {
        try {
            // 刷新容器前
            preRefresh();
            // 执行前置处理器
            preBeanPostProcessor(beanFactory);
            // 扫描包添加Bean定义对象
            initBeanDefinition(beanFactory);
            // 解析加有aspect注解的类
            parseCreateAspectBean(beanFactory);
            // 扫描BeanPostProcessor
            postProcessorBeanDefinitionRegistry(beanFactory);
            // 创建bean放入容器中
            initializingBeans(beanFactory);
            // 执行后置处理器
            postBeanPostProcessor(beanFactory, eventSourceManager);
            // 刷新容器后
            postRefresh();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void preRefresh() {
        startTime = System.currentTimeMillis();
        beanFactory = new DefaultBeanFactory();
        eventSourceManager = new EventSourceManager();
        MiracleUtils.registerBean("applicationContext", this);

        // 加载框架需要的监听器
        Set<String> classNames = ServiceClassLoader.getClassName(EventListener.class);
        List<EventListener> eventListeners = null;
        if (classNames != null) {
            eventListeners = classNames.stream()
                    .map(className -> {
                        try {
                            return (EventListener<?>) MiracleUtils.getClassLoader().loadClass(className).getConstructor().newInstance();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    })
                    .collect(Collectors.toList());
        }
        eventSourceManager.addEventListeners(eventListeners);
    }

    private void postRefresh() {
        // 发布容器启动完毕事件
        eventSourceManager.publishEvent(new ContextRefreshedEvent(null, startTime));
    }

    @Override
    public Object getBean(String name) {
        return beanFactory.getBean(name);
    }

    @Override
    public <T> T getBean(Class<T> aClass) {
        return beanFactory.getBean(aClass);
    }

    @Override
    public boolean containsBean(Class<?> aClass) {
        return beanFactory.containsBean(aClass);
    }

    @Override
    public boolean containsBean(String name) {
        return beanFactory.containsBean(name);
    }

    @Override
    public void registerBean(String name, Object bean) {
        beanFactory.registerBean(name, bean);
    }

    @Override
    public void close() {
        beanFactory.clean();
    }

    @Override
    public void publishEvent(EventObject eventObject) {
        eventSourceManager.publishEvent(eventObject);
    }

}
